package com.example.BMS_Disp_1;
/*
 * Display a battery view screen which connects with the controllers and shows voltages.
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Scanner;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ScrollView;
import android.widget.TextView;

public class Disp extends Activity {
	private static final String TAG = "BMS_Disp";
	public static final int SERVERPORT = 6699;
	private static final int SHOW_LOG = Menu.FIRST;
	private static final int SHOW_CELLS = Menu.FIRST + 1;
	private static final int SCROLL_MANUAL = Menu.FIRST + 2;
	private static final int SCROLL_AUTO = Menu.FIRST + 3;

    private final SimpleDateFormat mDateFormat = new SimpleDateFormat("HH:mm:ss");

    private GridView mGridViewText;
	private GridView mGridViewImg;
	private TextView mLogView;
	private ScrollView mScrollView;

	private boolean mShowingLog = true;		// show log first
	private boolean mShowGridImg = true;	// show image by default.
	
	private BatteryDB mDB;
	
	private Handler handler = new Handler();
	private boolean mScrollAuto = true;
 	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
		mGridViewImg = (GridView) findViewById(R.id.gridview1);
	    mGridViewText = (GridView) findViewById(R.id.gridview2);
	    mLogView = (TextView)findViewById(R.id.logView);
	    mScrollView = (ScrollView)findViewById(R.id.scrollView);
		registerForContextMenu(mLogView);
	    
	    //mLogView.setMovementMethod(new ScrollingMovementMethod());
	    
        Thread fst = new Thread(new ServerThread());
        fst.start();
 
		mDB = BatteryDB.getSingleton(this);
		mDB.open();
		showLog();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, SHOW_LOG, 0, R.string.menu_showLog);
		menu.add(0, SHOW_CELLS, 0, R.string.menu_showCells);
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case SHOW_LOG:
			showLog();
			break;

		case SHOW_CELLS:
			showCells();
			break;
		}	
		return super.onMenuItemSelected(featureId, item);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.add(0, SCROLL_MANUAL, 0, R.string.menu_scrollManual);
		menu.add(0, SCROLL_AUTO, 0, R.string.menu_scrollAuto);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case SCROLL_MANUAL:
			mScrollAuto = false;
			break;
		case SCROLL_AUTO:
			mScrollAuto  = true;
			break;
		}
		return super.onContextItemSelected(item);

	}

	@Override
	protected void onResume() {
		Log.d(TAG,"onResume");
		super.onResume();
	}
	
	private void showLog() {
		if (mShowingLog) return;
		
		mShowingLog = true;
		mLogView.setVisibility(android.view.View.VISIBLE);
		mScrollView.setVisibility(android.view.View.VISIBLE);
		mGridViewImg.setVisibility(android.view.View.INVISIBLE);;
		mGridViewText.setVisibility(android.view.View.INVISIBLE);;
	}
	private void showCells() {
		if (!mShowingLog) return;

		mShowingLog = false;
		mLogView.setVisibility(android.view.View.INVISIBLE);
		mScrollView.setVisibility(android.view.View.INVISIBLE);
		showGrid();	
	}
	private void toggleGrid() {
		mShowGridImg = !mShowGridImg;
		chooseImgOrTxt();
	}
	private void chooseImgOrTxt() {
		mGridViewImg.setVisibility(mShowGridImg? android.view.View.VISIBLE : android.view.View.INVISIBLE);
		mGridViewText.setVisibility(mShowGridImg? android.view.View.INVISIBLE: android.view.View.VISIBLE);
	}

	private void showGrid() {
        mGridViewImg.setAdapter(new CellAdapter(this, mDB, false));
        mGridViewImg.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            	toggleGrid();
            }
        });
        mGridViewText.setAdapter(new CellAdapter(this, mDB, true));
        mGridViewText.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            	toggleGrid();
            }
        });
        chooseImgOrTxt();
	}
 
	public String now() {
		return mDateFormat.format(Calendar.getInstance().getTime());
	}

	private void log(final String text) {
		handler.post(new Runnable() {
			public void run() {
				mLogView.append(now() + " " + text+"\n");
				if (mScrollAuto)
					mScrollView.fullScroll(View.FOCUS_DOWN);
			}
    	});
	}
	
    public class ServerThread implements Runnable {
    	
    	public void run() {
    		ServerSocket serverSocket = null;
    		
       		while (true) {
       			try {
       				serverSocket = new ServerSocket(SERVERPORT);
       				serverSocket.setSoTimeout(0);
       				handleArduinoInput(serverSocket);
    			} catch (Exception e) {
    					Log.d(TAG, e.toString());
 	               		e.printStackTrace();
	               		log("Exception in Socket Server: " + e.toString());
		    	} finally {
		    		try {
		    			serverSocket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
		    	}
            }
    	}
    	
    	private void handleArduinoInput(ServerSocket serverSocket) {
    		Socket client = null;
    		try {
    			log("waiting...");
    			client = serverSocket.accept();
    		} catch (IOException e) {
    			// ignore.. could be interrupted
    			Log.d(TAG,"handleArduinoInput, exc:"+e.toString());
    			return;
    		}
    		try {
				client.setSoLinger(false, 0);
				Log.d(TAG, "Connected");
				log("Connected to Arduino!");
	    		BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
	    		String line;
	    		while ((line = br.readLine()) != null) {
	    			Log.d(TAG, line);
	    			log(line);
	    			Scanner scanner = new Scanner(line);
	    			if (!scanner.hasNext()) {
	    				continue;
	    			}
	    			String cmd = scanner.next();
	   				if (cmd.equalsIgnoreCase("<cells>")) {
	   					while (scanner.hasNext()) {	
	   						int cell = scanner.nextInt();
	   						float val = scanner.nextFloat();
	   						Log.d(TAG, Integer.toString(cell) + ":" + Float.toString(val) + "\n");
	   						writeDB(cell,val);
	   					}
	   					display();
	   				}
				}
	    		br.close();
	    		Log.d(TAG,"done reading from client");
	    		client.close();
    		} catch (Exception e) {
    			Log.w(TAG, "handleArduinoInput,after client,Exc: "+ e.toString());
    			log("Client exception: " + e.toString());
    		}
    	}

		private void writeDB(int cell, float val) {
			mDB.setVoltage(cell, val);
		}
		public void display() {
			if (mShowingLog) return;
			
			handler.post(new Runnable() {
				public void run() {
					showGrid();
				}
		    	});
		}
    }

 

}